home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Programmer Disk
/
The Programmer Disk (Microforum).iso
/
xpro
/
tutor
/
pro1
/
app2.doc
< prev
next >
Wrap
Text File
|
1990-08-02
|
31KB
|
887 lines
xiii
THE 8086 INSTRUCTION SET
Before I go through the instructions I need to say something
about the structure of the instructions. For the majority of
instructions, two bits in the first instruction byte and the
whole second byte determine whether it is a byte or word
instruction and whether it is:
1. register, register
2. register, memory
3. memory, register
These refer to the 8 arithmetic registers, not the segment
registers. "Memory" is any allowable addressing mode. Therefore,
it is simpler to abbreviate this as:
reg/mem, reg/mem
This will always mean:
1. either a byte or word operation is allowed
2. any of the above 3 possibilities is allowed
unless specifically stated otherwise. Another possibility is the
operations with constants:
add ax, 7
xor sign_flag, 80h
These follow the same form. There are two possibilities:
1. register, constant
2. memory, constant
where this may be a byte or a word, "register" is any arithmetic
register, and "memory" is any allowable addressing mode. These
will be abbreviated:
reg/mem, constant
If we are taliking about a segment register, they will be
abbreviated:
segreg
If anything does not follow this pattern, it will be explicitly
stated.
DESTINATION,SOURCE
The standard way of writing instructions is with the destination
on the left and the source on the right:
______________________
The PC Assembler Tutor - Copyright (C) 1989 Chuck Nelson
The PC Assembler Tutor xiv
______________________
add destination, source
The register or memory location on the left ALWAYS gets the
result of the operation. The thing on the right is the second
operand (if any).
ADDRESSING MODES
These are the natural (default) segments of all addressing modes:
(1) DS
variable + (constant)
[bx] + (constant)
[si] + (constant)
[di] + (constant)
[bx+si] + (constant)
[bx+di] + (constant)
(2) SS
[bp] + (constant)
[bp+si] + (constant)
[bp+di] + (constant)
Where the constant is optional. Segment overrides may be used.
The segment overrides are:
SEGMENT OVERRIDE MACHINE CODE (hex)
CS: 2E
DS: 3E
ES: 26
SS: 36
These default segments apply to all instructions except the
string instructions, which will be explained individually.
THE INSTRUCTION SET
AAA (ascii adjust for addition) adjusts AL, assuming that it
contains the result of a legitimate unpacked BCD addition. If the
lower half-byte has generated a result 10 or over, it subtracts
10, carries 1 to AH, and sets the carry flag. If the result is 9
or less, it clears CF. In either case it zeroes the upper
half-byte of AL.
AAD (ascii adjust for division) PREPARES AL and AH for division.
It assumes that AH contains the 10's digit and AL contains the
1's digit of a two byte unpacked BCD number. It multiplies AH by
10 and adds it to AL, thus making a single integer between 0 and
99. It zeroes AH in preparation for unsigned division.
Appendix II - The 8086 Instruction Set xv
______________________________________
AAM (ascii adjust for multiplication) adjusts AL, assuming that
it contains the result of a legitimate BCD multiplication. It
divides the result by 10, putting the quotient in AH and the
remainder in AL. If AL contains 73 before AAM, then afterwards AH
will contain 7 and AL will contain 3
AAS (ascii adjust for subtraction) adjusts AL, assuming that it
contains the result of a legitimate unpacked BCD subtraction. If
the lower half-byte has generated a result -1 or less, it borrows
1 from AH, adds 10 to AL, and sets the carry flag. If the result
is 0 or more, it clears CF. In either case it zeroes the upper
half-byte of AL.
ADC (add with carry) adds two integers, either signed or
unsigned, and adds in the carry from the previous arithmetic
operation. It is used for multiple word (byte) addition.
adc reg/mem, reg/mem
adc reg/mem, constant
ADD adds two integers, either signed or unsigned.
add reg/mem, reg/mem
add reg/mem, constant
AND ands two bytes or words. A bit remains set only if both its
respective source and destination bits were set.
and reg/mem, reg/mem
and reg/mem, constant
CALL calls a procedure. The two forms we have used are NEAR and
FAR calls.
call set_regs
call FAR PTR calculate_array
There are two other forms where the addresses of the subprograms
are in memory and changable. You should only use these forms if
you are writing an operating system or a compiler, since they are
an invitation to disaster.
CBW sign extends the signed byte in AL to AH:AL in preparation
for signed division. It is used alone without any register
specification.
cbw
The PC Assembler Tutor xvi
______________________
CLC clears the carry flag (CF = 0).
CLD clears the direction flag (increments string pointers).
CLI clears the interrupt flag (disables interrupts). All maskable
interrupts must wait till the flag is set again before they will
be processed.
CMC changes the value of the carry flag. If CF =1, then CF = 0;
if CF = 0, then CF = 1.
CMP compares two values. It is the same as SUB except it does not
alter the "destination" variable. Its job is to set the flags as
if a subtraction had been performed, in preparation for a
conditional jump instruction.
cmp reg/mem, reg/mem
cmp reg/mem, constant
CMPS compares the byte (or word) at DS:[si] with the one at
ES:[di], (calculating [si] - [di]) and sets the flags
accordingly. It increments (or decrements) SI and DI depending on
the setting of DF, the direction flag (by 1 for bytes and by 2
for words). You may use CS:[si], SS:[si] or ES:[si], but you MAY
NOT OVERRIDE ES:[di]. Notice that SI and DI are reversed from
their position in the other string instructions.
cmpsb
cmpsw
cmps BYTE PTR SS:[si], ES:[di] ;or CS, DS, ES:[si]
cmps WORD PTR SS:[si], ES:[di] ;or CS, DS, ES:[si]
CWD sign extends the signed integer in AX to DX:AX in preparation
for signed word division. No register specification is used.
cwd
DAA (decimal adjust for addition) adjusts AL, assuming that it
contains the result of a legitimate packed BCD addition. It
treats AL as two independent half-bytes. If the result of the
lower half-byte is 10 or over, it subtracts 10 from the lower
half-byte and adds the carry to the upper half byte. It then
looks at the upper half byte. If its result is 10 or over, DAA
subtracts 10 from the upper half byte and sets the carry flag.
Appendix II - The 8086 Instruction Set xvii
______________________________________
Otherwise the carry flag is cleared.
DAS (decimal adjust for subtraction) adjusts AL, assuming that it
contains the result of a legitimate packed BCD subtraction.It
treats AL as two independent half-bytes. If the result of the
lower half-byte is -1 or less, it adds 10 to the lower half-byte
and borrows 1 from the upper half byte. It then looks at the
upper half byte. If its result is -1 or less, DAA adds 10 to the
upper half byte and sets the carry flag to indicate a borrow.
Otherwise the carry flag is cleared.
DEC decrements the byte or word by 1. It does not alter CF.
dec reg/mem
DIV performs unsigned division. If byte division, the unsigned
double byte must be in AH:AL. Afterwards, AL has the quotient and
AH has the remainder. If word division, the unsigned word must be
in DX:AX. Afterwards, AX has the quotient, and DX the remainder.
Division by a constant is not allowed. The DIV instruction does
not mention DX:AX or AH:AL. They are understood.
div reg/mem
ESC (escape) signals to the 8086 that the bytes starting with the
ESC byte are a coprocessor instruction. The 8086 will calculate a
memory address (if appropriate) and give it to the coprocessor.
The 8086 will then go on to the next instruction.
HLT (halt) halts the machine. It can be restarted with a reset, a
non-maskable interrupt, or (if IEF is set) with a maskable
interrupt.
IDIV performs signed integer division. For byte division, the
value in AL must be sign extended to AH (with CBW), giving the
double signed byte AH:AL, after division, AL contains the
quotient and AH contains the remainder. For word division, the
value in AX must be sign extended to DX (with CWD), giving the
double signed word DX:AX, after division, AX contains the
quotient and DX contains the remainder. Division by a constant is
not allowed. IDIV cannot perform multiple word division. To do
that, you need to make the numbers positive and use DIV,
adjusting the signs afterwards. IDIV does not mention the AL or
AX register, it is understood.
The PC Assembler Tutor xviii
______________________
idiv reg/mem
IMUL performs signed integer multiplication. The multiplicand
must be in AX (or AL for bytes). After the multiplication, the
result is in DX:AX for words and AH:AL for bytes. If DX (or AH
for bytes) contains significant information, then CF is set (=1).
If all the information is in AX (or AL for bytes) then CF = 0.
Multiplication by a constant is not allowed. The IMUL instruction
does not mention AX (or AL); it is understood.
imul mem/reg
IN allows you to move data from a port address to AX (for a word)
or AL (for a byte). There are two forms:
IN al, port_number
IN al, dx
Where 'port_number' is a CONSTANT that is hard coded into the
machine instruction and is from 0 - 255. The port address in DX
may be from 0-65535. It must be the DX register.
INC increments a register or a variable by 1. It does not effect
CF.
inc reg/mem
INT (interrupt) sends the program to a subprogram whose address
is located in the interrupt vector table in low memory. For any
interrupt number I, the 8086 goes to segment 0000, offset
(I X 4). It loads IP with the first two bytes, then loads CS from
the next two bytes. The next instruction executed will be at the
new CS:IP. Before loading the new CS and IP, it pushes (1) the
flags, (2) the old CS and (3) the old IP in that order.
int 3
int 21h
INTO checks OF. If OF = 1, INTO generates interrupt 4. Otherwise
it does nothing. It is used for error handling of signed numbers.
into
IRET (interrupt return) is a special return instruction for
interrupt routines. It pops (1) the old IP, (2) the old CS, and
(3) the old flags in that order.
Appendix II - The 8086 Instruction Set xix
______________________________________
iret
JUMPS ---------------------------------------------------------
There are two kinds of jumps. JMP is unconditional and can jump
anywhere in the segment. All other jumps are conditional and are
limited jumps from -128 to +127 bytes from the END of the jump
instruction.{1}
THESE ARE THE JUMP INSTRUCTIONS FOR SIGNED NUMBERS
jg ; jump if greater
jnle ; jump if not (less or equal)
jl ; jump if less
jnge ; jump if not (greater or equal)
je ; jump if equal
jz ; jump if zero
jge ; jump if greater or equal
jnl ; jump if not less
jle ; jump if less or equal
jng ; jump if not greater
jne ; jump if not equal
jnz ; jump if not zero
THESE ARE THE JUMP INSTRUCTIONS FOR UNSIGNED NUMBERS
ja ; jump if above
jnbe ; jump if not (below or equal)
jb ; jump if below
jnae ; jump if not (above or equal)
je ; jump if equal
jz ; jump if zero
jae ; jump if above or equal
jnb ; jump if not below
jbe ; jump if below or equal
jna ; jump if not above
____________________
1 There is also a long jump which can jump anywhere in memory
(from 00000 to FFFFF). Except under special circumstances, using
this is truly lousy programming practice. The long jump is for
the Olympics, not for quality programming.
The PC Assembler Tutor xx
______________________
jne ; jump if not equal
jnz ; jump if not zero
THESE JUMPS CHECK A SINGLE FLAG
These come in opposite pairs
jc ; jump if the carry flag is set
jnc ; jump if the carry flag is not set
jo ; jump if the overflow flag is set
jno ; jump if the overflow flag is not set
jp or jpe ; jump if parity flag is set (parity is even)
jnp or jpo ;jump if parity flag is not set (parity is odd)
js ; jump if the sign flag is set (negative )
jns ; jump if the sign flag is not set (positive or 0)
THIS CHECKS THE CX REGISTER
jcxz ; jump if cx is zero
This is used before entry to a loop to make sure the loop counter
is not set to 0.
INDIRECT JUMPS are jumps where the information for the jump is
stored in memory (or in a register for an in-segment jump). These
forms are dangerous and should be used only when writing things
like multi-tasking operating systems. Have you written one
lately?
END OF JUMPS - - - - - - - - - - - - - - - - - - - - - - -
LAHF (load AH from flags) loads the lower half of the flags
register into AH.
LDS (load DS) loads the first two bytes of the memory address
into the named arithmetic register and the next two bytes into
DS. The register may be any arithmetic register, but this is
designed for the 4 addressing registers: BX, SI, DI and BP.
lds reg, memory_address
LEA calculates an offset address and puts it in the named
register.
Appendix II - The 8086 Instruction Set xxi
______________________________________
lea ax, [bp+si]+145
LES (load ES) loads the first two bytes into the named arithmetic
register and the next two bytes into ES. The register may be any
arithmetic register, but this is designed for the 4 addressing
registers: BX, SI, DI and BP.
les reg, memory_address
LOCK is for use if there is more than one 8086 operating in a
computer. LOCK allows one 8086 to be the only one which can read
from or write to memory during the following instruction.
LODS moves a byte or word from DS:[si] to AL or AX, and
increments (or decrements) SI depending on the setting of DF, the
direction flag (by 1 for bytes and by 2 for words). You may use
CS:[si], SS:[si] or ES:[si].
lodsb
lodsw
lods BYTE PTR SS:[si] ; or CS, DS, ES:[si]
lods WORD PTR SS:[si] ; or CS, DS, ES:[si]
LOOP/LOOPE/LOOPNE are conditional jumps (-128 to + 127 bytes).
They will jump back to the start of the loop (which is identified
by a label), under the following conditions:
loop decrement cx ; jump back if cx is not zero
loope decrement cx ; jump back if cx not zero AND zf = 1
loopz decrement cx ; jump back if cx not zero AND zf = 1
loopne decrement cx ; jump back if cx not zero AND zf = 0
loopnz decrement cx ; jump back if cx not zero AND zf = 0
Here, 'e' stands for equal, 'z' is zero and 'n' is not.
loop some_label
MOV is the general instruction for moving bytes or words on the
8086. The forms are:
reg/mem, reg/mem
reg/mem, constant
segreg, reg/mem
reg/mem, segreg
Notice that you may not (1) move a constant to a segment
register, (2) move a segment register to another segment
The PC Assembler Tutor xxii
______________________
register, or (3) move from memory to memory.
MOVS moves a byte (or a word) from DS:[si] to ES:[di], and
increments (or decrements) SI and DI depending on the setting of
DF, the direction flag (by 1 for bytes and by 2 for words). You
may use CS:[si], SS:[si] or ES:[si], but you MAY NOT OVERRIDE
ES:[di].
movsb
movsw
movs BYTE PTR ES:[di], SS:[si] ;or CS, DS, ES:[si]
movs WORD PTR ES:[di], SS:[si] ;or CS, DS, ES:[si]
MUL performs unsigned integer multiplication. The multiplicand
must be in AX (or AL for bytes). After the multiplication, the
result is in DX:AX (or AH:AX for bytes). If DX (or AH for bytes)
contains significant information, then CF = 1. If all the
significant information is in AX (or AL for bytes) then CF = 0.
Multiplication by a constant is not allowed. The MUL instruction
does not mention AX (or AL). It is understood.
mul reg/mem
NEG performs '0 - number' on a number and sets the flags
accordingly.
neg reg/mem
NOP (no operation) does absolutely nothing. It can fill up space
which was previously occupied by a different instruction.
NOT performs bitwise logical NOT on a word or a byte.
not reg/mem
OR performs bitwise logical OR on a byte or word
or reg/mem, reg/mem
or reg/mem, constant
OUT moves a byte (or word) from AL (or AX) to the named port.
There are two forms:
Appendix II - The 8086 Instruction Set xxiii
______________________________________
out port_number, ax
out dx, ax
where 'port_number' is a CONSTANT which is coded into the machine
code. The constant may be from 0-255. DX (and it must be DX) may
hold a port number from 0-65535.
POP pops a WORD off the stack. Technically, POP takes the word at
SS:SP and puts it into the named register or memory location,
then ADDS 2 to SP.
pop mem/reg
pop segreg
POPF pops a WORD off the top of the stack into the flags
register. Its technical operation is the same as for POP.
PUSH pushes a WORD on the stack from the named register or memory
location. Technically, PUSH subtracts 2 from SP, then moves the
word to SS:SP.
push reg/mem
push segreg
PUSHF pushes the flags register on the stack. Its technical
operation is the same as for PUSH.
RCR (rotate through carry right) and RCL (rotate through carry
left) rotate the bits of a register or of memory data right and
left respectively. The bit which is shoved off the register (or
data) is placed in CF and CF is placed on the other side of the
register (or data). There are two fixed forms. (1) rotate 1 bit
and (2) rotate by the number in CL.
rcr reg/mem, 1
rcl reg/mem, cl
REP. The string instructions may be prefixed by REP/REPE/REPNE
which will repeat the instructions according to the following
conditions:
rep decrement cx ; repeat if cx is not zero
repe decrement cx ; repeat if cx not zero AND zf = 1
repz decrement cx ; repeat if cx not zero AND zf = 1
repne decrement cx ; repeat if cx not zero AND zf = 0
The PC Assembler Tutor xxiv
______________________
repnz decrement cx ; repeat if cx not zero AND zf = 0
Here, 'e' stands for equal, 'z' is zero and 'n' is not. These
repeat instructions should NEVER be used with a segment override,
since the 8086 will forget the override if a hardware interrupt
occurs in the middle of the REP loop.
rep movsb
repe scasb
repne cmpsw
RET returns from the subroutine to the calling program. The
return will be either NEAR or FAR depending on the type of
procedure it is in. It may take the parameters off the stack (for
Pascal) or leave them on the stack (for C).
ret (6) ; Pascal - take 6 bytes off the stack
ret ; C - do nothing
ROR (rotate right) and ROL (rotate left) rotate the bits of a
register or memory data right and left respectively. The bit
which is shoved off one end is moved to the other end. CF
indicates whether the last bit moved from one end to the other
was a 1 or a 0. There are two fixed forms. (1) rotate 1 bit and
(2) rotate by the number in CL.
ror reg/mem, 1
rol reg/mem, cl
SAHF (store AH into flags) puts AH into the low byte of the flags
register.
SAL (shift arithmetic left) and SHL (shift logical left) are
exactly the same instruction. They move bits left. 0s are placed
in the low bit. Bits are shoved off the register or memory data
on the left side, and CF indicates whether the last bit shoved
off was a 1 or a 0. It is used for multiplying an unsigned number
by powers of 2. There are two fixed forms. (1) shift 1 bit and
(2) shift by the number in CL.
shl reg/mem, 1
sal reg/mem, cl
SAR (shift arithmetic right) shifts bits right. The high (sign)
bit stays the same throughout the operation. Bits are shoved off
the register or memory location on the right side. CF indicates
whether the last bit shoved off was a 1 or a 0. It is used (with
Appendix II - The 8086 Instruction Set xxv
______________________________________
difficulty) for dividing a signed number by powers of 2. There
are two fixed forms. (1) shift 1 bit and (2) shift by the number
in CL.
sar reg/mem, 1
sar reg/mem, cl
SBB (subtract with borrow) subtracts one integer from another and
then subtracts 1 more if CF is set. It works with both signed and
unsigned numbers and is used for multiple word arithmetic.
sbb reg/mem, reg/mem
sbb reg/mem, constant
SCAS compares AL (or AX) to the byte (or word) pointed to by
ES:[di], and increments (or decrements) DI depending on the
setting of DF, the direction flag (by 1 for bytes and by 2 for
words). NO OVERRIDES ARE ALLOWED.
scasb
scasw
scas BYTE PTR ES:[di] ; no override allowed
scas WORD PTR ES:[di] ; no override allowed
SHR (shift logical right) does the same thing as SHL but in the
opposite direction. Bits are shifted right. 0s are placed in the
high bit. Bits are shoved off the register or memory location on
the right side and CF indicates whether the last bit shoved off
was a 0 or a 1. It is used for dividing an unsigned number by
powers of 2. There are two fixed forms. (1) shift 1 bit and (2)
shift by the number in CL.
shr reg/mem, 1
shr reg/mem, cl
STC sets the carry flag (CF = 1).
STD sets the direction flag (DF = 1, which decrements).
STI sets the interrupt flag (IEF = 1; interrupts enabled).
STOS (store to string) moves a byte (or a word) from AL (or AX)
to ES:[di], and increments (or decrements) DI depending on the
setting of DF, the direction flag (by 1 for bytes and by 2 for
words). NO SEGMENT OVERRIDES ARE ALLOWED.
stosb
The PC Assembler Tutor xxvi
______________________
stosw
stos BYTE PTR ES:[di] ; no override allowed
stos WORD PTR ES:[di] ; no override allowed
SUB subtracts one integer from another. It works for both signed
and unsigned numbers.
sub reg/mem, reg/mem
sub reg/mem, constant
TEST performs logical AND, but does not alter the value of the
"destination" variable. Its purpose is to set the flags for
conditional jumps.
test reg/mem, reg/mem
test reg/mem, constant
WAIT forces the 8086 to wait until the coprocessor is finished
with its instruction before the 8086 can go on to the next
instruction.
XCHG exchanges the values in two registers or memory locations.
xchg reg/mem, reg/mem
XLAT. If BX contains the address of a 256 byte translation table,
then XLAT goes to (BX + AL), takes the byte there and puts it
into AL. DS is the normal segment, but segment overrides are
allowed.
XOR performs logical exclusive OR on two numbers.
xor reg/mem, reg/mem
xor reg/mem, constant